Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 1e0f71378ff34dfef8c0ae261dcbf089186da719


Parents : c5de3e8
Author : Ivan <ivan@quad4.io>
Signature : Invalid signer <e46112d44649266d71fe2193e00a4710>, author is <ivan@quad4.io>
Date : 2026-07-07T22:58:48-05:00

refactor(cleanup): remove unused bot templates, privacy mode functions, and frontend components to streamline the codebase

Changes
Diff

diff --git a/meshchatx/src/backend/bot_templates.py b/meshchatx/src/backend/bot_templates.py
index be6d0897..9b1d6a9c 100644
--- a/meshchatx/src/backend/bot_templates.py
+++ b/meshchatx/src/backend/bot_templates.py
@@ -6,8 +6,6 @@ from datetime import UTC, datetime, timedelta
from lxmfy import IconAppearance, LXMFBot, pack_icon_appearance_field
-HAS_LXMFY = True
-
class StoppableBot:
def __init__(self):

diff --git a/meshchatx/src/backend/privacy_mode.py b/meshchatx/src/backend/privacy_mode.py
index db91edad..108664be 100644
--- a/meshchatx/src/backend/privacy_mode.py
+++ b/meshchatx/src/backend/privacy_mode.py
@@ -22,7 +22,3 @@ def ensure_outbound_http_allowed(config, *, feature: str = "outbound HTTP") -> N
if privacy_mode_enabled(config):
msg = f"Privacy mode is enabled; {feature} is blocked"
raise OutboundHttpBlockedError(msg)
-
-
-def csp_allows_external_sources(config) -> bool:
- return not privacy_mode_enabled(config)

diff --git a/meshchatx/src/frontend/components/CardStack.vue b/meshchatx/src/frontend/components/CardStack.vue
deleted file mode 100644
index 35578159..00000000
--- a/meshchatx/src/frontend/components/CardStack.vue
+++ /dev/null
@@ -1,154 +0,0 @@
-<!-- SPDX-License-Identifier: 0BSD -->
-
-<template>
- <div class="card-stack-wrapper flex-1 flex flex-col min-h-0" :class="{ 'is-expanded': isExpanded }">
- <div
- v-if="items && items.length > 0"
- class="relative"
- :class="{ 'stack-mode': !isExpanded && items.length > 1, 'grid-mode': isExpanded || items.length === 1 }"
- >
- <!-- Grid Mode (Expanded or only 1 item) -->
- <div v-if="isExpanded || items.length === 1" :class="gridClass" class="flex-1 min-h-0">
- <div v-for="(item, index) in items" :key="index" class="w-full">
- <slot :item="item" :index="index"></slot>
- </div>
- </div>
-
- <!-- Stack Mode (Collapsed and > 1 item) -->
- <div v-else class="relative flex-1 min-h-[320px]" :style="{ minHeight: stackHeight + 'px' }">
- <div
- v-for="(item, index) in stackedItems"
- :key="index"
- class="absolute inset-x-0 top-0 transition-all duration-300 ease-in-out cursor-pointer"
- :style="getStackStyle(index)"
- @click="onCardClick(index)"
- >
- <slot :item="item" :index="index"></slot>
-
- <!-- Overlay for non-top cards -->
- <div
- v-if="index > 0"
- class="absolute inset-0 bg-white/20 dark:bg-black/20 rounded-[inherit] pointer-events-none"
- ></div>
- </div>
-
- <!-- Controls -->
- <div v-if="items.length > 1" class="absolute -bottom-2 right-0 flex items-center gap-2 z-60">
- <div class="text-xs font-mono text-gray-500 dark:text-gray-400 mr-2">
- {{ activeIndex + 1 }} / {{ items.length }}
- </div>
- <button
- class="p-1.5 rounded-full bg-gray-100 dark:bg-zinc-800 hover:bg-gray-200 dark:hover:bg-zinc-700 text-gray-700 dark:text-gray-300 transition shadow-xs border border-gray-200 dark:border-zinc-700"
- title="Previous"
- @click.stop="prev"
- >
- <MaterialDesignIcon icon-name="chevron-left" class="size-5" />
- </button>
- <button
- class="p-1.5 rounded-full bg-gray-100 dark:bg-zinc-800 hover:bg-gray-200 dark:hover:bg-zinc-700 text-gray-700 dark:text-gray-300 transition shadow-xs border border-gray-200 dark:border-zinc-700"
- title="Next"
- @click.stop="next"
- >
- <MaterialDesignIcon icon-name="chevron-right" class="size-5" />
- </button>
- </div>
- </div>
- </div>
-
- <div v-if="items && items.length > 1" class="mt-4 flex justify-center">
- <button
- class="flex items-center gap-1.5 px-4 py-1.5 rounded-full bg-gray-100 dark:bg-zinc-800 hover:bg-gray-200 dark:hover:bg-zinc-700 text-xs font-bold text-gray-700 dark:text-gray-300 transition shadow-xs border border-gray-200 dark:border-zinc-700 uppercase tracking-wider"
- @click="isExpanded = !isExpanded"
- >
- <MaterialDesignIcon :icon-name="isExpanded ? 'collapse-all' : 'expand-all'" class="size-4" />
- {{ isExpanded ? "Collapse Stack" : `Show All ${items.length}` }}
- </button>
- </div>
- </div>
-</template>
-
-<script>
-import MaterialDesignIcon from "./MaterialDesignIcon.vue";
-
-export default {
- name: "CardStack",
- components: {
- MaterialDesignIcon,
- },
- props: {
- items: {
- type: Array,
- required: true,
- },
- maxVisible: {
- type: Number,
- default: 3,
- },
- stackHeight: {
- type: Number,
- default: 320,
- },
- gridClass: {
- type: String,
- default: "grid grid-cols-1 gap-4",
- },
- },
- data() {
- return {
- isExpanded: false,
- activeIndex: 0,
- };
- },
- computed: {
- stackedItems() {
- // Reorder items so the active item is at index 0
- const result = [];
- const count = Math.min(this.items.length, this.maxVisible);
-
- for (let i = 0; i < count; i++) {
- const idx = (this.activeIndex + i) % this.items.length;
- result.push(this.items[idx]);
- }
-
- return result;
- },
- },
- methods: {
- next() {
- this.activeIndex = (this.activeIndex + 1) % this.items.length;
- },
- prev() {
- this.activeIndex = (this.activeIndex - 1 + this.items.length) % this.items.length;
- },
- onCardClick(index) {
- if (index > 0) {
- // If clicked a background card, bring it to front
- this.activeIndex = (this.activeIndex + index) % this.items.length;
- }
- },
- getStackStyle(index) {
- if (this.isExpanded) return {};
-
- const offset = 8; // px
- const scaleReduce = 0.05;
-
- return {
- zIndex: 50 - index,
- transform: `translateY(${index * offset}px) scale(${1 - index * scaleReduce})`,
- opacity: 1 - index * 0.2,
- pointerEvents: index === 0 ? "auto" : "auto",
- };
- },
- },
-};
-</script>
-
-<style scoped>
-.card-stack-wrapper {
- width: 100%;
-}
-
-.stack-mode {
- perspective: 1000px;
-}
-</style>

diff --git a/meshchatx/src/frontend/components/call/RingtoneEditorModal.vue b/meshchatx/src/frontend/components/call/RingtoneEditorModal.vue
deleted file mode 100644
index 75379424..00000000
--- a/meshchatx/src/frontend/components/call/RingtoneEditorModal.vue
+++ /dev/null
@@ -1,528 +0,0 @@
-<!-- SPDX-License-Identifier: 0BSD -->
-
-<template>
- <div class="fixed inset-0 z-100 flex items-center justify-center p-4 sm:p-6">
- <div class="absolute inset-0 bg-zinc-900/80 backdrop-blur-xs" @click="$emit('close')"></div>
- <div
- class="relative w-full max-w-4xl bg-white dark:bg-zinc-900 rounded-3xl shadow-2xl overflow-hidden flex flex-col max-h-[90vh]"
- >
- <!-- Header -->
- <div class="px-6 py-4 border-b border-gray-100 dark:border-zinc-800 flex items-center justify-between">
- <div>
- <h3 class="text-lg font-bold text-gray-900 dark:text-white">Edit Ringtone</h3>
- <p class="text-xs text-gray-500 dark:text-zinc-500">{{ ringtone.display_name }}</p>
- </div>
- <button
- class="p-2 hover:bg-gray-100 dark:hover:bg-zinc-800 rounded-full transition-colors"
- @click="$emit('close')"
- >
- <MaterialDesignIcon icon-name="close" class="size-6 text-gray-500" />
- </button>
- </div>
-
- <!-- Content -->
- <div class="flex-1 overflow-y-auto p-6 space-y-6">
- <!-- Waveform Container -->
- <div
- class="relative bg-gray-50 dark:bg-zinc-800/50 rounded-2xl p-4 border border-gray-100 dark:border-zinc-800 min-h-[200px] flex flex-col justify-center"
- >
- <div v-if="loading" class="flex flex-col items-center justify-center space-y-3">
- <div
- class="size-8 border-4 border-blue-500/20 border-t-blue-500 rounded-full animate-spin"
- ></div>
- <p class="text-sm text-gray-500 dark:text-zinc-400 font-medium">Loading audio...</p>
- </div>
-
- <div v-show="!loading" class="relative">
- <canvas
- ref="waveform"
- class="w-full h-40 cursor-pointer"
- @mousedown="handleWaveformClick"
- ></canvas>
-
- <!-- Playback Progress -->
- <div
- class="absolute top-0 bottom-0 w-0.5 bg-blue-500 z-10 pointer-events-none"
- :style="{ left: progressPercent + '%' }"
- ></div>
-
- <!-- Selection Overlays -->
- <div
- class="absolute top-0 bottom-0 bg-blue-500/10 border-x-2 border-blue-500 z-20"
- :style="{ left: startPercent + '%', width: endPercent - startPercent + '%' }"
- >
- <!-- Handles -->
- <div
- class="absolute top-1/2 -left-3 -translate-y-1/2 size-6 bg-white dark:bg-zinc-700 border-2 border-blue-500 rounded-full shadow-lg cursor-ew-resize flex items-center justify-center group"
- @mousedown.stop.prevent="startDragging('start')"
- >
- <div class="w-0.5 h-3 bg-blue-500 group-hover:h-4 transition-all"></div>
- </div>
- <div
- class="absolute top-1/2 -right-3 -translate-y-1/2 size-6 bg-white dark:bg-zinc-700 border-2 border-blue-500 rounded-full shadow-lg cursor-ew-resize flex items-center justify-center group"
- @mousedown.stop.prevent="startDragging('end')"
- >
- <div class="w-0.5 h-3 bg-blue-500 group-hover:h-4 transition-all"></div>
- </div>
- </div>
- </div>
- </div>
-
- <!-- Controls -->
- <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
- <div class="space-y-4">
- <div class="flex items-center justify-between">
- <span class="text-sm font-bold text-gray-700 dark:text-zinc-300">Time Range</span>
- <span class="text-[10px] font-mono text-gray-500"
- >{{ formatTime(startTime) }} - {{ formatTime(endTime) }} ({{
- formatTime(endTime - startTime)
- }})</span
- >
- </div>
- <div class="flex gap-4">
- <div class="flex-1">
- <label class="block text-[10px] uppercase font-bold text-gray-400 mb-1">Start</label>
- <input
- v-model.number="startTime"
- type="number"
- step="0.01"
- min="0"
- :max="endTime"
- class="w-full bg-gray-50 dark:bg-zinc-800 border-none rounded-lg text-sm px-3 py-2 focus:ring-2 focus:ring-blue-500 text-gray-900 dark:text-white"
- />
- </div>
- <div class="flex-1">
- <label class="block text-[10px] uppercase font-bold text-gray-400 mb-1">End</label>
- <input
- v-model.number="endTime"
- type="number"
- step="0.01"
- :min="startTime"
- :max="totalDuration"
- class="w-full bg-gray-50 dark:bg-zinc-800 border-none rounded-lg text-sm px-3 py-2 focus:ring-2 focus:ring-blue-500 text-gray-900 dark:text-white"
- />
- </div>
- </div>
- </div>
-
- <div class="flex flex-col justify-end">
- <button
- class="flex items-center justify-center gap-2 py-3 rounded-xl font-bold transition-all w-full"
- :class="
- isPlaying
- ? 'bg-orange-500 text-white shadow-lg shadow-orange-500/20'
- : 'bg-blue-600 text-white shadow-lg shadow-blue-500/20'
- "
- @click="togglePlay"
- >
- <MaterialDesignIcon :icon-name="isPlaying ? 'pause' : 'play'" class="size-5" />
- {{ isPlaying ? "Pause Selection" : "Play Selection" }}
- </button>
- </div>
- </div>
- </div>
-
- <!-- Footer -->
- <div
- class="px-6 py-4 bg-gray-50 dark:bg-zinc-800/30 border-t border-gray-100 dark:border-zinc-800 flex items-center justify-between"
- >
- <div class="flex items-center gap-2">
- <input
- id="saveAsNew"
- v-model="saveAsNew"
- type="checkbox"
- class="rounded-sm border-gray-300 text-blue-600 focus:ring-blue-500"
- />
- <label for="saveAsNew" class="text-sm text-gray-600 dark:text-zinc-400 cursor-pointer"
- >Save as new ringtone</label
- >
- </div>
- <div class="flex items-center gap-3">
- <button
- class="px-4 py-2 text-sm font-bold text-gray-500 hover:text-gray-700 dark:hover:text-zinc-300 transition-colors"
- @click="$emit('close')"
- >
- Cancel
- </button>
- <button
- :disabled="saving || loading"
- class="px-6 py-2 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-xl text-sm font-bold shadow-lg transition-all hover:scale-[1.02] active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
- @click="save"
- >
- <MaterialDesignIcon v-if="saving" icon-name="loading" class="size-4 animate-spin" />
- {{ saving ? "Saving..." : "Save Audio" }}
- </button>
- </div>
- </div>
- </div>
- </div>
-</template>
-
-<script>
-import MaterialDesignIcon from "../MaterialDesignIcon.vue";
-import ToastUtils from "../../js/ToastUtils";
-
-export default {
- name: "RingtoneEditorModal",
- components: {
- MaterialDesignIcon,
- },
- props: {
- ringtone: {
- type: Object,
- required: true,
- },
- },
- emits: ["close", "saved"],
- data() {
- return {
- loading: true,
- saving: false,
- audioBuffer: null,
- audioContext: null,
- sourceNode: null,
- startTime: 0,
- endTime: 0,
- totalDuration: 0,
- isPlaying: false,
- playbackStartTime: 0,
- playbackStartOffset: 0,
- progressPercent: 0,
- animationFrame: null,
- dragging: null,
- saveAsNew: false,
- };
- },
- computed: {
- startPercent() {
- return (this.startTime / this.totalDuration) * 100 || 0;
- },
- endPercent() {
- return (this.endTime / this.totalDuration) * 100 || 100;
- },
- },
- mounted() {
- this.loadAudio();
- window.addEventListener("mousemove", this.handleDragging);
- window.addEventListener("mouseup", this.stopDragging);
- window.addEventListener("resize", this.drawWaveform);
- },
- beforeUnmount() {
- this.stopPlayback();
- window.removeEventListener("mousemove", this.handleDragging);
- window.removeEventListener("mouseup", this.stopDragging);
- window.removeEventListener("resize", this.drawWaveform);
- if (this.audioContext) {
- this.audioContext.close();
- }
- },
- methods: {
- async loadAudio() {
- try {
- this.loading = true;
- const response = await fetch(`/api/v1/telephone/ringtones/${this.ringtone.id}/audio`);
- const arrayBuffer = await response.arrayBuffer();
-
- this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
- this.audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer);
-
- this.totalDuration = this.audioBuffer.duration;
- this.startTime = 0;
- this.endTime = this.totalDuration;
-
- this.$nextTick(() => {
- this.drawWaveform();
- });
- } catch (e) {
- console.error("Failed to load audio:", e);
- ToastUtils.error(this.$t("call.failed_load_audio_edit"));
- this.$emit("close");
- } finally {
- this.loading = false;
- }
- },
- drawWaveform() {
- const canvas = this.$refs.waveform;
- if (!canvas || !this.audioBuffer) return;
-
- const ctx = canvas.getContext("2d");
- const width = canvas.clientWidth;
- const height = canvas.clientHeight;
-
- // Set canvas internal resolution
- canvas.width = width * window.devicePixelRatio;
- canvas.height = height * window.devicePixelRatio;
- ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
-
- const data = this.audioBuffer.getChannelData(0);
- const step = Math.ceil(data.length / width);
- const amp = height / 2;
-
- ctx.clearRect(0, 0, width, height);
- ctx.beginPath();
- ctx.moveTo(0, amp);
-
- // Draw a nice modern waveform
- ctx.strokeStyle = this.isDarkMode() ? "#3f3f46" : "#e4e4e7";
- ctx.lineWidth = 1;
-
- for (let i = 0; i < width; i++) {
- let min = 1.0;
- let max = -1.0;
- for (let j = 0; j < step; j++) {
- const datum = data[i * step + j];
- if (datum < min) min = datum;
- if (datum > max) max = datum;
- }
- ctx.moveTo(i, amp + min * amp);
- ctx.lineTo(i, amp + max * amp);
- }
- ctx.stroke();
-
- // Highlight the selected range
- const startX = (this.startTime / this.totalDuration) * width;
- const endX = (this.endTime / this.totalDuration) * width;
-
- ctx.beginPath();
- ctx.strokeStyle = "#3b82f6";
- ctx.lineWidth = 1.5;
- for (let i = Math.floor(startX); i < Math.ceil(endX); i++) {
- let min = 1.0;
- let max = -1.0;
- for (let j = 0; j < step; j++) {
- const datum = data[i * step + j];
- if (datum < min) min = datum;
- if (datum > max) max = datum;
- }
- ctx.moveTo(i, amp + min * amp);
- ctx.lineTo(i, amp + max * amp);
- }
- ctx.stroke();
- },
- isDarkMode() {
- return document.documentElement.classList.contains("dark");
- },
- formatTime(seconds) {
- const mins = Math.floor(seconds / 60);
- const secs = (seconds % 60).toFixed(2);
- return `${mins}:${secs.padStart(5, "0")}`;
- },
- startDragging(type) {
- this.dragging = type;
- },
- stopDragging() {
- this.dragging = null;
- this.drawWaveform();
- },
- handleDragging(e) {
- if (!this.dragging) return;
-
- const canvas = this.$refs.waveform;
- const rect = canvas.getBoundingClientRect();
- const x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
- const time = (x / rect.width) * this.totalDuration;
-
- if (this.dragging === "start") {
- this.startTime = Math.min(time, this.endTime - 0.1);
- } else if (this.dragging === "end") {
- this.endTime = Math.max(time, this.startTime + 0.1);
- }
- },
- handleWaveformClick(e) {
- const canvas = this.$refs.waveform;
- const rect = canvas.getBoundingClientRect();
- const x = e.clientX - rect.left;
- const time = (x / rect.width) * this.totalDuration;
-
- // If click is outside selection, move nearest boundary
- if (time < this.startTime) {
- this.startTime = time;
- } else if (time > this.endTime) {
- this.endTime = time;
- } else {
- // If click is inside, maybe we can use it to seek preview
- // but for now let's just keep it simple
- }
- this.drawWaveform();
- },
- togglePlay() {
- if (this.isPlaying) {
- this.stopPlayback();
- } else {
- this.startPlayback();
- }
- },
- startPlayback() {
- if (!this.audioBuffer) return;
-
- this.stopPlayback();
-
- this.sourceNode = this.audioContext.createBufferSource();
- this.sourceNode.buffer = this.audioBuffer;
- this.sourceNode.connect(this.audioContext.destination);
-
- this.playbackStartOffset = this.startTime;
- this.playbackStartTime = this.audioContext.currentTime;
-
- this.sourceNode.start(0, this.startTime, this.endTime - this.startTime);
- this.isPlaying = true;
-
- this.sourceNode.onended = () => {
- this.isPlaying = false;
- this.progressPercent = 0;
- cancelAnimationFrame(this.animationFrame);
- };
-
- this.updateProgress();
- },
- stopPlayback() {
- if (this.sourceNode) {
- this.sourceNode.stop();
- this.sourceNode = null;
- }
- this.isPlaying = false;
- this.progressPercent = 0;
- cancelAnimationFrame(this.animationFrame);
- },
- updateProgress() {
- if (!this.isPlaying) return;
-
- const elapsed = this.audioContext.currentTime - this.playbackStartTime;
- const currentTime = this.playbackStartOffset + elapsed;
- this.progressPercent = (currentTime / this.totalDuration) * 100;
-
- if (currentTime >= this.endTime) {
- this.stopPlayback();
- return;
- }
-
- this.animationFrame = requestAnimationFrame(this.updateProgress);
- },
- async save() {
- try {
- this.saving = true;
-
- // Create a trimmed version of the audio
- const sampleRate = this.audioBuffer.sampleRate;
- const startSample = Math.floor(this.startTime * sampleRate);
- const endSample = Math.floor(this.endTime * sampleRate);
- const frameCount = endSample - startSample;
-
- const offlineCtx = new OfflineAudioContext(this.audioBuffer.numberOfChannels, frameCount, sampleRate);
-
- const trimmedBuffer = offlineCtx.createBuffer(
- this.audioBuffer.numberOfChannels,
- frameCount,
- sampleRate
- );
-
- for (let channel = 0; channel < this.audioBuffer.numberOfChannels; channel++) {
- const data = this.audioBuffer.getChannelData(channel);
- const trimmedData = trimmedBuffer.getChannelData(channel);
- for (let i = 0; i < frameCount; i++) {
- trimmedData[i] = data[startSample + i];
- }
- }
-
- // Convert AudioBuffer to WAV blob
- const blob = this.audioBufferToWav(trimmedBuffer);
-
- const formData = new FormData();
- const filename = this.saveAsNew ? `edited_${this.ringtone.filename}` : this.ringtone.filename;
-
- formData.append("file", blob, filename);
-
- if (this.saveAsNew) {
- await window.api.post("/api/v1/telephone/ringtones/upload", formData, {
- headers: { "Content-Type": "multipart/form-data" },
- });
- } else {
- // We don't have a direct "replace" endpoint, but we can delete and upload,
- // or just upload as a new one.
- // For now let's just upload as a new one if it's simpler,
- // but the user might expect replacement.
- // The backend doesn't seem to support direct replacement via the upload endpoint.
- // Let's just upload it.
- await window.api.post("/api/v1/telephone/ringtones/upload", formData, {
- headers: { "Content-Type": "multipart/form-data" },
- });
-
- // If not saving as new, maybe delete the old one?
- // await window.api.delete(`/api/v1/telephone/ringtones/${this.ringtone.id}`);
- }
-
- ToastUtils.success(this.$t("call.ringtone_saved"));
- this.$emit("saved");
- this.$emit("close");
- } catch (e) {
- console.error("Failed to save ringtone:", e);
- ToastUtils.error(this.$t("call.failed_save_ringtone"));
- } finally {
- this.saving = false;
- }
- },
- audioBufferToWav(buffer) {
- const numOfChan = buffer.numberOfChannels;
- const length = buffer.length * numOfChan * 2 + 44;
- const buffer_arr = new ArrayBuffer(length);
- const view = new DataView(buffer_arr);
- const channels = [];
- let i;
- let sample;
- let offset = 0;
- let pos = 0;
-
- const setUint16 = (data) => {
- view.setUint16(pos, data, true);
- pos += 2;
- };
-
- const setUint32 = (data) => {
- view.setUint32(pos, data, true);
- pos += 4;
- };
-
- const writeString = (string) => {
- for (let i = 0; i < string.length; i++) {
- view.setUint8(pos + i, string.charCodeAt(i));
- }
- pos += string.length;
- };
-
- writeString("RIFF");
- setUint32(length - 8);
- writeString("WAVE");
- writeString("fmt ");
- setUint32(16);
- setUint16(1);
- setUint16(numOfChan);
- setUint32(buffer.sampleRate);
- setUint32(buffer.sampleRate * 2 * numOfChan);
- setUint16(numOfChan * 2);
- setUint16(16);
- writeString("data");
- setUint32(length - pos - 4);
-
- for (i = 0; i < buffer.numberOfChannels; i++) channels.push(buffer.getChannelData(i));
-
- while (pos < length) {
- for (i = 0; i < numOfChan; i++) {
- sample = Math.max(-1, Math.min(1, channels[i][offset]));
- sample = (sample < 0 ? sample * 0x8000 : sample * 0x7fff) | 0;
- view.setInt16(pos, sample, true);
- pos += 2;
- }
- offset++;
- }
-
- return new Blob([buffer_arr], { type: "audio/wav" });
- },
- },
-};
-</script>
-
-<style scoped>
-canvas {
- image-rendering: pixelated;
-}
-</style>

diff --git a/meshchatx/src/frontend/components/network-visualiser/internal/trailUtils.js b/meshchatx/src/frontend/components/network-visualiser/internal/trailUtils.js
deleted file mode 100644
index 379eb2f9..00000000
--- a/meshchatx/src/frontend/components/network-visualiser/internal/trailUtils.js
+++ /dev/null
@@ -1,16 +0,0 @@
-export function getPositionAlongTrail(trail, distBehind) {
- if (!trail || trail.length === 0) return { x: 0, y: 0 };
- if (trail.length === 1) return { ...trail[0] };
- let d = 0;
- for (let i = trail.length - 1; i > 0; i--) {
- const p = trail[i];
- const q = trail[i - 1];
- const seg = Math.hypot(p.x - q.x, p.y - q.y);
- if (d + seg >= distBehind) {
- const t = seg > 0 ? (distBehind - d) / seg : 0;
- return { x: p.x + (q.x - p.x) * t, y: p.y + (q.y - p.y) * t };
- }
- d += seg;
- }
- return { ...trail[0] };
-}

diff --git a/meshchatx/src/frontend/components/network-visualiser/internal/viewBounds.js b/meshchatx/src/frontend/components/network-visualiser/internal/viewBounds.js
deleted file mode 100644
index 435c008b..00000000
--- a/meshchatx/src/frontend/components/network-visualiser/internal/viewBounds.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export function getViewCanvasBounds(network) {
- const container = document.getElementById("network");
- if (!container || !network) return null;
- const scale = network.getScale();
- const vp = network.getViewPosition();
- const w = container.clientWidth;
- const h = container.clientHeight;
- const halfW = w / (2 * scale);
- const halfH = h / (2 * scale);
- return {
- left: vp.x - halfW,
- right: vp.x + halfW,
- top: vp.y - halfH,
- bottom: vp.y + halfH,
- scale,
- };
-}

diff --git a/scripts/repository_http_server.py b/scripts/repository_http_server.py
deleted file mode 100644
index 31ad3380..00000000
--- a/scripts/repository_http_server.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: 0BSD
-"""CLI wrapper: plain HTTP file server for a MeshChatX repository-server directory."""
-
-import sys
-from pathlib import Path
-
-_repo_root = Path(__file__).resolve().parents[1]
-if str(_repo_root) not in sys.path:
- sys.path.insert(0, str(_repo_root))
-
-from meshchatx.repository_http_standalone import main # noqa: E402
-
-if __name__ == "__main__":
- raise SystemExit(main())

diff --git a/tests/backend/map_benchmarks.py b/tests/backend/map_benchmarks.py
deleted file mode 100644
index 9bf78963..00000000
--- a/tests/backend/map_benchmarks.py
+++ /dev/null
@@ -1,197 +0,0 @@
-# SPDX-License-Identifier: 0BSD
-
-import gc
-import json
-import os
-import random
-import secrets
-import shutil
-import tempfile
-import time
-from unittest.mock import MagicMock
-
-import psutil
-
-from meshchatx.src.backend.database import Database
-
-
-def get_memory_usage():
- """Returns current process memory usage in MB."""
- process = psutil.Process(os.getpid())
- return process.memory_info().rss / (1024 * 1024)
-
-
-def generate_hash():
- return secrets.token_hex(16)
-
-
-class MapBenchmarker:
- def __init__(self):
- self.results = []
- self.temp_dir = tempfile.mkdtemp()
- self.db_path = os.path.join(self.temp_dir, "map_perf_test.db")
- self.db = Database(self.db_path)
- self.db.initialize()
- self.identity_hash = generate_hash()
-
- def cleanup(self):
- self.db.close()
- shutil.rmtree(self.temp_dir)
-
- def record_benchmark(self, name, operation, iterations=1):
- gc.collect()
- start_mem = get_memory_usage()
- start_time = time.time()
-
- operation()
-
- end_time = time.time()
- gc.collect()
- end_mem = get_memory_usage()
-
- duration = (end_time - start_time) / iterations
- mem_diff = end_mem - start_mem
-
- result = {
- "name": name,
- "duration_ms": duration * 1000,
- "memory_growth_mb": mem_diff,
- "iterations": iterations,
- }
- self.results.append(result)
- print(f"Benchmark: {name}")
- print(f" Avg Duration: {result['duration_ms']:.2f} ms")
- print(f" Memory Growth: {result['memory_growth_mb']:.2f} MB")
- return result
-
- def benchmark_telemetry_insertion(self, count=1000):
- def run_telemetry():
- with self.db.provider:
- for i in range(count):
- self.db.telemetry.upsert_telemetry(
- destination_hash=generate_hash(),
- timestamp=time.time(),
- data=os.urandom(100), # simulate packed telemetry
- received_from=generate_hash(),
- )
-
- self.record_benchmark(
- f"Telemetry Insertion ({count} entries)",
- run_telemetry,
- count,
- )
-
- def benchmark_telemetry_retrieval(self, count=100):
- # Seed some data first
- dest_hash = generate_hash()
- for i in range(500):
- self.db.telemetry.upsert_telemetry(
- destination_hash=dest_hash,
- timestamp=time.time() - i,
- data=os.urandom(100),
- )
-
- def run_retrieval():
- for _ in range(count):
- self.db.telemetry.get_telemetry_history(dest_hash, limit=100)
-
- self.record_benchmark(
- f"Telemetry History Retrieval ({count} calls)",
- run_retrieval,
- count,
- )
-
- def benchmark_drawing_storage(self, count=500):
- # Create a large GeoJSON-like string
- dummy_data = json.dumps(
- {
- "type": "FeatureCollection",
- "features": [
- {
- "type": "Feature",
- "geometry": {
- "type": "Point",
- "coordinates": [
- random.uniform(-180, 180),
- random.uniform(-90, 90),
- ],
- },
- "properties": {"name": f"Marker {i}"},
- }
- for i in range(100)
- ],
- },
- )
-
- def run_drawings():
- with self.db.provider:
- for i in range(count):
- self.db.map_drawings.upsert_drawing(
- identity_hash=self.identity_hash,
- name=f"Layer {i}",
- data=dummy_data,
- )
-
- self.record_benchmark(
- f"Map Drawing Insertion ({count} layers)",
- run_drawings,
- count,
- )
-
- def benchmark_drawing_listing(self, count=100):
- def run_list():
- for _ in range(count):
- self.db.map_drawings.get_drawings(self.identity_hash)
-
- self.record_benchmark(f"Map Drawing Listing ({count} calls)", run_list, count)
-
- def benchmark_mbtiles_listing(self, count=100):
- from meshchatx.src.backend.map_manager import MapManager
-
- # Mock config
- config = MagicMock()
- config.map_mbtiles_dir.get.return_value = self.temp_dir
-
- # Create some dummy .mbtiles files
- for i in range(5):
- with open(os.path.join(self.temp_dir, f"test_{i}.mbtiles"), "w") as f:
- f.write("dummy")
-
- mm = MapManager(config, self.temp_dir)
-
- def run_list():
- for _ in range(count):
- mm.list_mbtiles()
-
- self.record_benchmark(
- f"MBTiles Listing ({count} calls, 5 files)",
- run_list,
- count,
- )
-
-
-def main():
- print("Starting Map-related Performance Benchmarking...")
- bench = MapBenchmarker()
- try:
- bench.benchmark_telemetry_insertion(1000)
- bench.benchmark_telemetry_retrieval(100)
- bench.benchmark_drawing_storage(500)
- bench.benchmark_drawing_listing(100)
- bench.benchmark_mbtiles_listing(100)
-
- print("\n" + "=" * 80)
- print(f"{'Benchmark Name':40} | {'Avg Time':10} | {'Mem Growth':10}")
- print("-" * 80)
- for r in bench.results:
- print(
- f"{r['name']:40} | {r['duration_ms']:8.2f} ms | {r['memory_growth_mb']:8.2f} MB",
- )
- print("=" * 80)
-
- finally:
- bench.cleanup()
-
-
-if __name__ == "__main__":
- main()

diff --git a/tests/backend/memory_benchmarks.py b/tests/backend/memory_benchmarks.py
deleted file mode 100644
index 8523e873..00000000
--- a/tests/backend/memory_benchmarks.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# SPDX-License-Identifier: 0BSD
-
-import gc
-import os
-import random
-import secrets
-import shutil
-import tempfile
-import time
-
-import psutil
-
-from meshchatx.src.backend.database import Database
-from meshchatx.src.backend.recovery import CrashRecovery
-
-
-def get_memory_usage():
- """Returns current process memory usage in MB."""
- process = psutil.Process(os.getpid())
- return process.memory_info().rss / (1024 * 1024)
-
-
-def generate_hash():
- return secrets.token_hex(16)
-
-
-class PerformanceBenchmarker:
- def __init__(self):
- self.results = []
- self.temp_dir = tempfile.mkdtemp()
- self.db_path = os.path.join(self.temp_dir, "perf_test.db")
- self.db = Database(self.db_path)
- self.db.initialize()
- self.my_hash = generate_hash()
-
- def cleanup(self):
- self.db.close()
- shutil.rmtree(self.temp_dir)
-
- def record_benchmark(self, name, operation, iterations=1):
- gc.collect()
- start_mem = get_memory_usage()
- start_time = time.time()
-
- operation()
-
- end_time = time.time()
- gc.collect()
- end_mem = get_memory_usage()
-
- duration = (end_time - start_time) / iterations
- mem_diff = end_mem - start_mem
-
- result = {
- "name": name,
- "duration_ms": duration * 1000,
- "memory_growth_mb": mem_diff,
- "iterations": iterations,
- }
- self.results.append(result)
- print(f"Benchmark: {name}")
- print(f" Avg Duration: {result['duration_ms']:.2f} ms")
- print(f" Memory Growth: {result['memory_growth_mb']:.2f} MB")
- return result
-
- def benchmark_message_flood(self, count=1000):
- peer_hashes = [generate_hash() for _ in range(50)]
-
- def run_flood():
- for i in range(count):
- peer_hash = random.choice(peer_hashes)
- is_incoming = i % 2 == 0
- msg = {
- "hash": generate_hash(),
- "source_hash": peer_hash if is_incoming else self.my_hash,
- "destination_hash": self.my_hash if is_incoming else peer_hash,
- "peer_hash": peer_hash,
- "state": "delivered",
- "progress": 1.0,
- "is_incoming": is_incoming,
- "method": "direct",
- "delivery_attempts": 1,
- "title": f"Flood Msg {i}",
- "content": "X" * 1024, # 1KB content
- "fields": "{}",
- "timestamp": time.time(),
- "rssi": -50,
- "snr": 5.0,
- "quality": 3,
- "is_spam": 0,
- }
- self.db.messages.upsert_lxmf_message(msg)
-
- self.record_benchmark(f"Message Flood ({count} msgs)", run_flood, count)
-
- def benchmark_conversation_fetching(self):
- def fetch_convs():
- for _ in range(100):
- self.db.messages.get_conversations()
-
- self.record_benchmark("Fetch 100 Conversations Lists", fetch_convs, 100)
-
- def benchmark_crash_recovery_overhead(self):
- recovery = CrashRecovery(
- storage_dir=self.temp_dir,
- database_path=self.db_path,
- public_dir=os.path.join(self.temp_dir, "public"),
- )
- os.makedirs(recovery.public_dir, exist_ok=True)
- with open(os.path.join(recovery.public_dir, "index.html"), "w") as f:
- f.write("test")
-
- def run_recovery_check():
- for _ in range(50):
- # Simulate the periodic or manual diagnosis check
- recovery.run_diagnosis(file=open(os.devnull, "w"))
-
- self.record_benchmark(
- "CrashRecovery Diagnosis Overhead (50 runs)",
- run_recovery_check,
- 50,
- )
-
- def benchmark_identity_generation(self, count=20):
- import RNS
-
- def run_gen():
- for _ in range(count):
- RNS.Identity(create_keys=True)
-
- self.record_benchmark(
- f"RNS Identity Generation ({count} identities)",
- run_gen,
- count,
- )
-
- def benchmark_identity_listing(self, count=100):
- from meshchatx.src.backend.identity_manager import IdentityManager
-
- # We need to create identities with real DBs to test listing performance
- manager = IdentityManager(self.temp_dir)
-
- hashes = []
- for i in range(10):
- res = manager.create_identity(f"Test {i}")
- hashes.append(res["hash"])
-
- def run_list():
- for _ in range(count):
- manager.list_identities(current_identity_hash=hashes[0])
-
- self.record_benchmark(
- f"Identity Listing ({count} runs, 10 identities)",
- run_list,
- count,
- )
-
- def benchmark_announce_trim(self, seed_count=800, runs=40):
- aspect = "lxmf.delivery"
-
- def seed():
- with self.db.provider:
- for _ in range(seed_count):
- self.db.announces.upsert_announce(
- {
- "destination_hash": generate_hash(),
- "aspect": aspect,
- "identity_hash": generate_hash(),
- "identity_public_key": "cHVibmtleQ==",
- "app_data": None,
- "rssi": None,
- "snr": None,
- "quality": None,
- },
- )
-
- seed()
-
- def run_trim():
- for _ in range(runs):
- self.db.announces.trim_announces_for_aspect(
- aspect,
- max(1, seed_count // 2),
- )
-
- self.record_benchmark(
- f"Announce trim ({seed_count} rows, {runs} trims)",
- run_trim,
- runs,
- )
-
-
-def main():
- print("Starting Backend Memory & Performance Benchmarking...")
- bench = PerformanceBenchmarker()
- try:
- bench.benchmark_message_flood(2000)
- bench.benchmark_conversation_fetching()
- bench.benchmark_crash_recovery_overhead()
- bench.benchmark_identity_generation()
- bench.benchmark_identity_listing()
- bench.benchmark_announce_trim()
-
- print("\n" + "=" * 80)
- print(f"{'Benchmark Name':40} | {'Avg Time':10} | {'Mem Growth':10}")
- print("-" * 80)
- for r in bench.results:
- print(
- f"{r['name']:40} | {r['duration_ms']:8.2f} ms | {r['memory_growth_mb']:8.2f} MB",
- )
- print("=" * 80)
-
- finally:
- bench.cleanup()
-
-
-if __name__ == "__main__":
- main()


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────